#ifndef PSD_CONN_H
#define PSD_CONN_H

#include "config.h"

#include <sys/time.h>
#include <fcntl.h>

#include "queue.h"

#include "libxsp_proto.h"
#include "psd_settings.h"
#include "psd_path.h"

enum psd_connection_status_t { STATUS_UNCONNECTED, STATUS_CONNECTED, STATUS_FROZEN };

typedef struct psd_connection_t {
	pthread_mutex_t lock;

	pthread_cond_t cond;

	enum psd_connection_status_t status;

	LIST_ENTRY(psd_connection_t) channel_entries;

	LIST_ENTRY(psd_connection_t) sess_entries;

	struct psd_session_t *session;

	char *id;

	char *hostname;

	char *description;

	char *protocol;

	struct psd_path_t *path;

	struct psd_channel_t *channel;

	psdSettings *settings;

	struct timeval start_time, end_time;

	
	int (*splice2) (struct psd_connection_t *src, struct psd_connection_t *sink, size_t len, int flags);
	int (*src_splice2) (struct psd_connection_t *conn, int fd, size_t len, int flags);
	int (*sink_splice2) (struct psd_connection_t *conn, int fd, size_t len, int flags);
	int (*read2) (struct psd_connection_t *src, void *buf, size_t len, int flags);
	int (*write2) (struct psd_connection_t *sink, const void *buf, size_t len, int flags);
        int (*set_session_status2) (struct psd_connection_t *sink, int status);
	int (*shutdown2) (struct psd_connection_t *conn, uint8_t direction);
	int (*setbufsize2) (struct psd_connection_t *conn, uint8_t direction, int size);
	int (*settimeout2) (struct psd_connection_t *conn, uint8_t direction, int seconds);
	void (*free_conn_private2) (struct psd_connection_t *conn);
	void (*free_stats2) (void *arg);

	xspMsg *(*get_msg2) (struct psd_connection_t *conn, unsigned int flags);
	int (*send_msg2) (struct psd_connection_t *conn, uint8_t type, void *msg_body);

	int (*get_stat2) (struct psd_connection_t *conn, uint16_t type, void *optval, size_t *optlen);

	void *auth_info;

	void *conn_private;

	void *stats_private;
} psdConn;

typedef struct psd_conn_stats_default_t {
	struct timeval connect_time;
	struct timeval shutdown_read_time;
	struct timeval shutdown_write_time;
	uint64_t bytes_read;
	uint64_t bytes_written;
} psdConn_defStats;

#define PSD_SEND_SIDE	0x01
#define PSD_RECV_SIDE	0x02

psdConn_defStats *psd_conn_stats_alloc_def();
psdConn *psd_conn_alloc();
void psd_conn_free(psdConn *conn);
void __psd_conn_free(psdConn *conn);
void psd_conn_free_stats_def(psdConn *conn);
int psd_conn_default_get_stat(psdConn *conn, uint16_t type, void *optval, size_t *optlen);
xspMsg *psd_conn_default_get_msg(psdConn *conn, unsigned int flags);
int psd_conn_default_set_session_status(psdConn *conn, int status);
int psd_conn_default_send_msg(psdConn *conn, uint8_t type, void *msg_body);

int psd_conn_src_splice(psdConn *conn, int fd, size_t len, int flags);
int psd_conn_sink_splice(psdConn *conn, int fd, size_t len, int flags);
int psd_conn_read(psdConn *conn, void *buf, size_t len, int flags);
int psd_conn_write(psdConn *conn, const void *buf, size_t len, int flags);
int psd_conn_set_session_status(psdConn *conn, int status);
int psd_conn_setbufsize(psdConn *conn, uint8_t direction, int size);
int psd_conn_settimeout(psdConn *conn, uint8_t direction, int seconds);
int psd_conn_shutdown(psdConn *conn, int side);
xspMsg *psd_conn_get_msg(psdConn *conn, unsigned int flags);
int psd_conn_send_msg(psdConn *conn, uint8_t type, void *msg_body);
int psd_conn_get_stat (psdConn *conn, uint16_t type, void *optval, size_t *optlen);


#endif
